import React from 'react'
import PropTypes from 'prop-types'
import { Dropdown, Button, message } from 'antd'
import { PlusOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons'
import Component, { mapStateToProps, mapDispatchToProps } from '@components/Component'
import { connect } from 'react-redux'
import { getOperateComponent } from './CaseModule'
import LazyLoad from '@components/LazyLoad'
import style from './OperateTags.module.less'
import Tab from './OperateTags/Tab'
import { addResizeEvent, delResizeEvent } from '@redux/actions'

class OperateTags extends Component {
  state = {
    usedOperate: [],
    unuseOperate: [],
    openedOperateKey: [],
    activeKey: '',
    scrollLeft: 0,
    isOver: true,
    ready: false
  }

  tabContainerRef = React.createRef()
  tabsRef = React.createRef()
  activeTabRef = React.createRef()

  closeTagHandle (i) {
    let { usedOperate, unuseOperate, activeKey } = this.state
    usedOperate = usedOperate.slice()
    unuseOperate = unuseOperate.slice()
    const usedKeys = usedOperate.map(li => li.key)
    this.closeOperateRequest(usedOperate[i].key)
    const len = usedOperate.length
    let key = activeKey
    if (activeKey === usedKeys[i]) {
      if (i === len - 1) {
        if (len > 1) {
          key = usedKeys[i - 1]
        } else {
          key = ''
        }
      } else if (i === 0) {
        key = usedKeys[1]
      } else {
        key = usedKeys[i - 1]
      }
    }
    const list = usedOperate.splice(i, 1)
    unuseOperate = unuseOperate.concat(list)
    const openedOperateKey = this.getNewOpened(key)
    this.setState({
      usedOperate, unuseOperate, activeKey: key, openedOperateKey
    }, () => {
      this.initLayout()
    })
  }

  // 获取新的已打开操作
  getNewOpened (key) {
    const openedOperateKey = this.state.openedOperateKey.slice()
    const index = openedOperateKey.indexOf(key)
    if (index === -1) {
      openedOperateKey.push(key)
    }
    return openedOperateKey
  }

  // 设置当前操作的模块
  selectActiveKey (key) {
    const usedOperate = this.state.usedOperate.slice()
    const unuseOperate = this.state.unuseOperate.slice()
    const unuseIndex = unuseOperate.indexOf(key)
    const openedOperateKey = this.getNewOpened(key)

    this.setState({
      activeKey: key,
      openedOperateKey
    }, () => {
      this.initLayout()
    })
    if (unuseIndex !== -1) {
      usedOperate.push(unuseOperate[unuseIndex])
      unuseOperate.splice(unuseIndex, 1)
      this.setState({
        usedOperate,
        unuseOperate
      }, () => {
        this.initLayout()
      })
    }
  }

  // 获取操作列表
  getOperateList () {
    return this.$get(`/api/xapc/case_operate/${this.props.id}`)
      .then(res => {
        if (res.status === 1) {
          const { used, unuse } = res.data
          const usedKeys = used.map(li => li.key)
          const unuseKeys = unuse.map(li => li.key)
          let activeKey = this.state.activeKey || (this.props.meta || {}).operate
          const keyInUsedIndex = usedKeys.indexOf(activeKey)
          const keyInUnuseIndex = unuseKeys.indexOf(activeKey)
          if (activeKey) {
            if (keyInUsedIndex === -1 && keyInUnuseIndex !== -1) {
              used.push(unuse[keyInUnuseIndex])
              unuse.splice(keyInUnuseIndex, 1)
            } else if (keyInUsedIndex === -1 && keyInUnuseIndex === -1) {
              activeKey = ''
            }
          } else {
            if (used.length) {
              activeKey = used[0].key
            } else if (unuse.length) {
              used.push(unuse[0])
              activeKey = unuse[0].key
              unuse.shift()
            } else {
              activeKey = ''
            }
          }
          this.setState({
            usedOperate: used,
            unuseOperate: unuse,
            activeKey,
            openedOperateKey: activeKey ? [activeKey] : []
          }, () => {
            if (!this.state.ready) {
              this.setState({
                ready: true
              })
              this.initActiveKey()
            }
          })
        } else {
          message.warning(res.message)
        }
      })
  }

  // 记录新增的操作
  openOperateRequest (operate) {
    this.$post('/api/xapc/case_operate', {
      caseid: this.props.id,
      operate
    })
  }

  // 清除操作
  closeOperateRequest (operate) {
    this.$delete('/api/xapc/case_operate', {
      caseid: this.props.id,
      operate
    })
  }

  // 打开标签
  openTag (operate) {
    const usedOperate = this.state.usedOperate.slice()
    const unuseOperate = this.state.unuseOperate.slice()
    const index = unuseOperate.map(li => li.key).indexOf(operate.key)
    if (index === -1) {
      return false
    }
    usedOperate.push(unuseOperate[index])
    unuseOperate.splice(index, 1)
    this.setState({
      unuseOperate,
      usedOperate,
      activeKey: operate.key,
      openedOperateKey: this.getNewOpened(operate.key)
    }, () => {
      this.initLayout()
    })
    this.openOperateRequest(operate.key)
  }

  // 初始化选中项
  initActiveKey () {
    const { operate } = this.props.meta || {}
    const { usedOperate, unuseOperate } = this.state
    if (!operate) {
      return this.initLayout()
    }
    const isUsed = usedOperate.find(li => li.key === operate) !== undefined
    const isUnUsed = unuseOperate.find(li => li.key === operate) !== undefined
    if (isUsed) {
      this.selectActiveKey(operate)
    } else if (isUnUsed) {
      this.openTag({ key: operate })
    }
  }

  // 格式化布局
  initLayout () {
    const tabContainer = this.tabContainerRef.current
    const tabs = this.tabsRef.current
    let activeTab = this.activeTabRef.current
    if (!tabContainer || !tabs || !activeTab) {
      return setTimeout(() => {
        this.initLayout()
      }, 100)
    }
    activeTab = activeTab.tab.current
    let containerWidth = tabContainer.offsetWidth
    const listWidth = tabs.offsetWidth
    const isOver = listWidth > containerWidth
    const activeLeft = activeTab.offsetLeft
    const activeWidth = activeTab.offsetWidth
    let scrollLeft = this.state.scrollLeft
    if (isOver) {
      containerWidth = containerWidth - 64
    }
    if (scrollLeft + activeLeft < 0) {
      scrollLeft = -activeLeft
    } else if (scrollLeft + activeLeft + activeWidth > containerWidth) {
      scrollLeft = containerWidth - (activeLeft + activeWidth)
    }
    if (listWidth < containerWidth) {
      scrollLeft = 0
    } else if (scrollLeft + listWidth < containerWidth) {
      scrollLeft = containerWidth - listWidth
    } else if (scrollLeft > 0) {
      scrollLeft = 0
    }
    this.setState({
      isOver,
      scrollLeft
    })
  }

  // 点击左侧按钮回调
  leftClickHandle () {
    const tabContainer = this.tabContainerRef.current
    const tabs = this.tabsRef.current
    let { scrollLeft, isOver } = this.state
    if (!tabContainer || !tabs) {
      return setTimeout(() => {
        this.leftClickHandle()
      }, 100)
    }
    const containerWidth = isOver ? tabContainer.offsetWidth - 64 : tabContainer.offsetWidth
    if (scrollLeft + containerWidth < 0) {
      scrollLeft = scrollLeft + containerWidth
    } else {
      scrollLeft = 0
    }
    this.setState({
      scrollLeft
    })
  }

  // 点击右侧按钮回调
  rightClickHandle () {
    const tabContainer = this.tabContainerRef.current
    const tabs = this.tabsRef.current
    let { scrollLeft, isOver } = this.state
    if (!tabContainer || !tabs) {
      return setTimeout(() => {
        this.rightClickHandle()
      }, 100)
    }
    const containerWidth = isOver ? tabContainer.offsetWidth - 64 : tabContainer.offsetWidth
    const tabsWidth = tabs.offsetWidth
    if (scrollLeft + tabsWidth - containerWidth > containerWidth) {
      scrollLeft = scrollLeft - containerWidth
    } else {
      scrollLeft = containerWidth - tabsWidth
    }
    this.setState({
      scrollLeft
    })
  }

  componentDidUpdate (prev) {
    if (prev.meta !== this.props.meta) {
      this.initActiveKey()
    }
    if (prev.caseDetail !== this.props.caseDetail && this.props.caseDetail) {
      this.getOperateList()
    }
  }

  componentDidMount () {
    if (this.props.caseDetail) {
      this.getOperateList()
    }
    this.props.addResizeEvent({
      name: `${this.props.id}-operate-tab`,
      handle: () => this.initLayout()
    })
  }

  componentWillUnmount () {
    this.props.delResizeEvent(`${this.props.id}-operate-tab`)
  }

  // 渲染标签列表
  renderTabList (active = false) {
    return this.state.usedOperate.map((li, i) => {
      const { activeKey } = this.state
      const isActive = li.key === activeKey
      return <Tab ref={isActive ? this.activeTabRef : null} key={li.key} title={li.title} active={isActive} onClick={() => this.selectActiveKey(li.key)} closeHandle={() => this.closeTagHandle(i)} />
    })
  }

  // 渲染标签页和其他按钮容器
  renderTabContainer () {
    const tabContainerClass = [style['tab-container']]
    const prevClass = [style['tab-btn'], style.prev]
    const nextClass = [style['tab-btn'], style.next]
    if (this.state.isOver) {
      tabContainerClass.push(style.over)
    } else {
      prevClass.push(style.hide)
      nextClass.push(style.hide)
    }
    return (
      <div className={style.header}>
        <div className={style['tab-extra']}>
          {this.renderDropdown()}
        </div>
        <div className={tabContainerClass.join(' ')} ref={this.tabContainerRef}>
          <div className={prevClass.join(' ')} onClick={() => this.leftClickHandle()}>
            <LeftOutlined />
          </div>
          <div className={nextClass.join(' ')} onClick={() => this.rightClickHandle()}>
            <RightOutlined />
          </div>
          <div className={style['tab-list']}>
            <div className={style.tabs} ref={this.tabsRef} style={{ left: `${this.state.scrollLeft}px` }}>
              {this.renderTabList()}
            </div>
          </div>
        </div>
      </div>
    )
  }

  // 渲染下拉按钮
  renderDropdown () {
    return (
      <Dropdown menu={this.renderMenus()} trigger={['click']}>
        <Button type='link' icon={<PlusOutlined />}>添加操作</Button>
      </Dropdown>
    )
  }

  // 渲染更多操作菜单
  renderMenus () {
    const menu = { items: [] }
    const list = this.state.unuseOperate
    if (list.length > 0) {
      list.forEach(operate => {
        menu.items.push({ label: operate.title, key: operate.key, onClick: () => { this.openTag(operate) } })
      })
    } else {
      menu.items.push({ label: '无其他操作', key: 0 })
    }
    return menu
  }

  // 渲染标签内容
  renderContent () {
    return (
      <div className={style.content}>
        {
          this.state.usedOperate.map(li => {
            const { activeKey } = this.state
            const loadFn = getOperateComponent(li)
            const s = [style['tab-pane']]
            if (li.key !== activeKey) {
              s.push(style.hide)
            }
            return (
              <div className={s.join(' ')} key={li.key}>
                {loadFn ? this.renderPane(li, loadFn) : <span>模块不存在</span>}
              </div>
            )
          })
        }
      </div>
    )
  }

  // 渲染操作页
  renderPane (li, loadFn) {
    const { editable, caseDetail, status, fullInfo, refreshCaseData } = this.props
    const { openedOperateKey } = this.state
    const unopened = openedOperateKey.indexOf(li.key) === -1
    if (unopened) {
      return null
    }
    return (
      <LazyLoad loadFn={loadFn} id={this.props.id} editable={editable} caseDetail={caseDetail} data={li} status={status} refreshCaseData={() => refreshCaseData()} close={() => this.closeTagHandle(li)} toFullInfo={() => fullInfo(this.props.meta.id)} />
    )
  }

  render () {
    if (!this.props.caseDetail) {
      return null
    }
    return (
      <div className={style.container}>
        {this.renderTabContainer()}
        {this.renderContent()}
      </div>
    )
  }
}

OperateTags.propTypes = {
  caseDetail: PropTypes.object,
  editable: PropTypes.bool,
  status: PropTypes.string,
  fullInfo: PropTypes.func,
  id: PropTypes.string,
  refreshCaseData: PropTypes.func,
  meta: PropTypes.object
}
OperateTags.defaultProps = {
  caseDetail: null,
  editable: false,
  status: '',
  fullInfo: () => {},
  id: '',
  refreshCaseData: () => {},
  meta: {}
}

const mapState = mapStateToProps(function (state) {
  return {
    userInfo: state.basic.userInfo
  }
})

const mapDispatch = mapDispatchToProps(function (dispatch) {
  return {
    addResizeEvent: i => dispatch(addResizeEvent(i)),
    delResizeEvent: i => dispatch(delResizeEvent(i))
  }
})

export default connect(mapState, mapDispatch)(OperateTags)
